<!--
 * Copyright © 2023
 * @Author: zhangxiang
 * @Date: 2023-05-29 11:06:52
 * @LastEditors: zhangxiang
 * @LastEditTime: 2023-09-28 09:51:35
 * @Description:
 *
-->

<template>
  <MyContainer class="flavor-ctn">
    <MyMain ref="mainCtn" class="main">
      <el-row type="flex" justify="center" style="padding: 0 20px">
        <el-button
          size="medium"
          icon="el-icon-upload2"
          type="primary"
          :loading="exportLoading"
          style="margin-left: auto"
          @click="exportClick"
        >全量导出</el-button>
      </el-row>
      <div id="treeCtn" ref="treeCtn" class="tree">
        <div class="column top" :style="{ 'min-width': treeBottomMinWidth }">
          <div id="tree-root" class="item">
            <div class="line"></div>
            <div class="content">云商规格清单</div>
            <div class="line"></div>
          </div>
        </div>
        <div class="column center" :style="{ 'min-width': treeBottomMinWidth }">
          <div
            v-for="(cloud, index) in allCloudVendor"
            :id="'cloud-' + index"
            :key="index"
            class="cloud"
          >
            {{ cloud.cloudName }}: {{ cloud.accountName }}
          </div>
        </div>
        <div class="column bottom" :style="{ 'min-width': treeBottomMinWidth }">
          <div
            v-for="(cloud, index) in allCloudVendor"
            :key="index"
            class="infos"
          >
            <div
              v-for="(info, findex) in infos"
              :id="'cloud-' + index + '-' + info"
              :key="findex"
              :class="[
                'info',
                info,
                activeIndex === index && activeInfo === info ? 'active' : '',
              ]"
              :style="{
                margin: info == 'flavor' ? '0 ' + flavorMargin + 'px' : '0',
              }"
              @click="infoClick(index, info)"
            >
              <div class="line"></div>
              <div :class="['content', info]">
                {{
                  info === "image"
                    ? "镜像信息"
                    : info === "flavor"
                      ? isCloudVendorPrivate(cloud.cloudVendor)
                        ? "规格能耗信息"
                        : "规格成本信息"
                      : "存储信息"
                }}
              </div>
              <div class="line"></div>
            </div>
          </div>
        </div>
      </div>
      <div class="list">
        <el-row class="filter" type="flex" align="middle">
          <template v-if="filterOptions.includes('regionId')">
            <span class="name">区域</span>
            <el-select
              v-model="regionId"
              placeholder="请选择区域"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="regionIdRemoteQuery"
              :loading="regionIdLoading"
              @change="regionIdChange"
            >
              <el-option
                v-for="(item, index) in regionIdOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('zoneId')">
            <span class="name">可用区</span>
            <el-select
              v-model="zoneId"
              placeholder="请选择可用区"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="zoneIdRemoteQuery"
              :loading="zoneIdLoading"
              @change="zoneIdChange"
            >
              <el-option
                v-for="(item, index) in zoneIdOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('privateRegion')">
            <span class="name">可用域</span>
            <el-select
              v-model="privateRegion"
              placeholder="请选择可用域"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="privateRegionRemoteQuery"
              :loading="privateRegionLoading"
              @change="privateRegionChange"
            >
              <el-option
                v-for="(item, index) in privateRegionOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('flavorId')">
            <span class="name">规格</span>
            <el-select
              v-model="flavorId"
              placeholder="请选择规格"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="flavorIdRemoteQuery"
              :loading="flavorIdLoading"
              @change="flavorIdChange"
            >
              <el-option
                v-for="(item, index) in flavorIdOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('imageId')">
            <span class="name">镜像</span>
            <el-select
              v-model="imageId"
              placeholder="请选择镜像"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="imageIdRemoteQuery"
              :loading="imageIdLoading"
              @change="imageIdChange"
            >
              <el-option
                v-for="(item, index) in imageIdOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('diskType')">
            <span class="name">磁盘类型</span>
            <el-select
              v-model="diskType"
              placeholder="请选择磁盘类型"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="diskTypeRemoteQuery"
              :loading="diskTypeLoading"
              @change="diskTypeChange"
            >
              <el-option
                v-for="(item, index) in diskTypeOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('format')">
            <span class="name">镜像格式</span>
            <el-select
              v-model="format"
              placeholder="请选择镜像格式"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="formatRemoteQuery"
              :loading="formatLoading"
              @change="formatChange"
            >
              <el-option
                v-for="(item, index) in formatOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('describe')">
            <span class="name">描述</span>
            <el-select
              v-model="describe"
              placeholder="请选择描述"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="describeRemoteQuery"
              :loading="describeLoading"
              @change="describeChange"
            >
              <el-option
                v-for="(item, index) in describeOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <template v-if="filterOptions.includes('cost')">
            <span class="name">价格</span>
            <el-select
              v-model="cost"
              placeholder="请选择价格"
              size="medium"
              style="width: 170px; margin-left: 10px; margin-right: 20px"
              filterable
              remote
              :remote-method="costRemoteQuery"
              :loading="costLoading"
              @change="costChange"
            >
              <el-option
                v-for="(item, index) in costOptions"
                :key="index"
                :label="item"
                :value="item"
              />
            </el-select>
          </template>
          <el-button
            size="medium"
            type="primary"
            :loading="loading"
            @click="queryClick"
          >查询</el-button>
          <el-button size="medium" @click="resetClick">重置</el-button>
          <el-button
            v-if="!activePrivate && activeInfo === 'flavor'"
            style="margin-left: auto"
            size="medium"
            type="primary"
            @click="agencyCostSetting"
          >设置代理价格</el-button>
        </el-row>

        <el-table
          v-loading="loading"
          class="custom-table"
          :data="list"
          header-cell-class-name="listHeaderCell"
          :header-cell-style="{ background: '#F3F3F3', color: '#696969' }"
        >
          <el-table-column prop="order" width="100" label="编号" />
          <el-table-column
            v-for="columnKey in columnOptions"
            :key="columnKey"
            :prop="columnKey"
            align="center"
            :min-width="columnOptionDetail[columnKey].minWidth"
            :label="
              columnKey === 'cloudType' && activePrivate
                ? '云服务商'
                : columnOptionDetail[columnKey].label
            "
          >
            <template slot-scope="scope">
              {{ columnKey === "cloudScope" ? "私有云" : scope.row[columnKey] }}
            </template>
          </el-table-column>
        </el-table>
        <el-row type="flex" justify="end" style="margin-top: 20px">
          <el-pagination
            background
            layout="total, sizes, prev, pager, next"
            :page-sizes="[5, 10, 15]"
            :page-size="pageSize"
            :current-page.sync="pageNo"
            :total="totalNum"
            @current-change="changePage"
            @size-change="sizeChange"
          />
        </el-row>
      </div>
    </MyMain>
    <AgencyCostSettingDialog
      v-if="showAgencyCostSettingDialog"
      :show.sync="showAgencyCostSettingDialog"
      :cloud-info="allCloudVendor[activeIndex]"
      @success="settingSuccessCallback"
    />
  </MyContainer>
</template>

<script>
import LeaderLine from 'leader-line'
import MyContainer from '@/components/Layout/MyContainer'
import MyMain from '@/components/Layout/MyMain'
import AgencyCostSettingDialog from './components/AgencyCostSettingDialog.vue'
import {
  getAllExport,
  getAllRegions,
  getAllZones,
  getAllPrivateRegions,
  getImageInfoForSelect,
  getImageFormatForSelect,
  getImageDescribeForSelect,
  getAllImageInfo,
  getDiskTypeInfoForSelect,
  getDiskTypeDescribeForSelect,
  getAllDiskTypeInfo,
  getFlavorInfoForSelect,
  getFlavorDescribeForSelect,
  getFlavorCostForSelect,
  getAllFlavorInfo
} from '@/api/cnap/scheduling-engine'
import { getAllCloudVendor } from '@/api/cnap/hybrid-cloud'
import { isPrivateCloud } from '@/utils/cnap/constant'

let allLeaderLines = []

export default {
  name: 'SchedulingEngineFlavor',
  components: {
    MyContainer,
    MyMain,
    AgencyCostSettingDialog
  },
  data() {
    return {
      exportLoading: false,
      treeBottomMinWidth: '1080px',
      flavorMargin: 0,
      allCloudVendor: [],
      infos: ['image', 'flavor', 'storage'],
      activeIndex: 0,
      activeInfo: 'image',
      activePrivate: false,
      filterOptions: [],
      columnOptions: [],
      columnOptionDetail: {
        cloudType: {
          prop: 'cloudType',
          minWidth: 120,
          label: '云商类型'
        },
        regionId: {
          prop: 'regionId',
          minWidth: 130,
          label: '区域'
        },
        zoneId: {
          prop: 'zoneId',
          minWidth: 130,
          label: '可用区'
        },
        flavorId: {
          prop: 'flavorId',
          minWidth: 150,
          label: '规格id'
        },
        imageId: {
          prop: 'imageId',
          minWidth: 220,
          label: '镜像id'
        },
        diskType: {
          prop: 'diskType',
          minWidth: 150,
          label: '磁盘类型'
        },
        describe: {
          prop: 'describe',
          minWidth: 160,
          label: '描述'
        },
        cost: {
          prop: 'cost',
          minWidth: 150,
          label: '价格（元/小时）'
        },
        agencyCost: {
          prop: 'agencyCost',
          minWidth: 160,
          label: '代理价格（元/小时）'
        },
        cloudScope: {
          prop: 'cloudScope',
          minWidth: 120,
          label: '云商类型'
        },
        accountName: {
          prop: 'accountName',
          minWidth: 120,
          label: '云账户'
        },
        format: {
          prop: 'format',
          minWidth: 120,
          label: '镜像格式'
        },
        privateRegion: {
          prop: 'privateRegion',
          minWidth: 120,
          label: '可用域'
        },
        pidle: {
          prop: 'pidle',
          minWidth: 120,
          label: '空闲功率（W）'
        },
        pmax: {
          prop: 'pmax',
          minWidth: 120,
          label: '最大功率（W）'
        }
      },
      regionId: '', // 区域
      zoneId: '', // 可用区
      privateRegion: '', // 可用域
      diskType: '', // 磁盘类型
      imageId: '', // 镜像
      flavorId: '', // 规格
      format: '', // 镜像格式
      describe: '', // 描述
      cost: '', // 成本
      regionIdOptions: [],
      regionIdLoading: false,
      zoneIdOptions: [],
      zoneIdLoading: false,
      privateRegionOptions: [],
      privateRegionLoading: false,
      diskTypeOptions: [],
      diskTypeLoading: false,
      imageIdOptions: [],
      imageIdLoading: false,
      flavorIdOptions: [],
      flavorIdLoading: false,
      formatOptions: [],
      formatLoading: false,
      describeOptions: [],
      describeLoading: false,
      costOptions: [],
      costLoading: false,
      loading: false, // 加载中
      pageSize: 5, // 页size
      pageNo: 1, // 页码
      totalNum: 0, // 总数
      list: [], // 列表
      showAgencyCostSettingDialog: false
    }
  },
  computed: {
    /**
     * @description: 侧边栏配置
     * @return {*}
     */
    sidebar() {
      return this.$store.state.app.sidebar
    }
  },
  created() {},
  mounted() {
    this.initData()
  },
  beforeDestroy() {
    // for (const leaderLine of allLeaderLines) {
    //   leaderLine.remove()
    // }
    // allLeaderLines = []
  },
  methods: {
    /**
     * @description: 设置代理价格成功回调
     * @return {*}
     */
    settingSuccessCallback() {
      this.$message.success({
        message: '设置代理价格成功！',
        duration: '1500'
      })
      this.queryClick()
    },
    /**
     * @description: 设置代理价格
     * @return {*}
     */
    agencyCostSetting() {
      this.showAgencyCostSettingDialog = true
    },
    /**
     * @description: 云商是否私有云
     * @param {*} key
     * @return {*}
     */
    isCloudVendorPrivate(key) {
      return isPrivateCloud(this.allCloudVendor, key)
    },
    /**
     * @description: 区域查询
     * @param {*} query
     * @return {*}
     */
    regionIdRemoteQuery(query) {
      this.regionIdLoading = true
      getAllRegions({
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName,
        regionId: query
      })
        .then((res) => {
          this.regionIdOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.regionIdLoading = false
        })
    },
    /**
     * @description: 可用区查询
     * @param {*} query
     * @return {*}
     */
    zoneIdRemoteQuery(query) {
      this.zoneIdLoading = true
      getAllZones({
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName,
        regionId: this.regionId,
        zoneId: query
      })
        .then((res) => {
          this.zoneIdOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.zoneIdLoading = false
        })
    },
    /**
     * @description: 可用域查询
     * @param {*} query
     * @return {*}
     */
    privateRegionRemoteQuery(query) {
      this.privateRegionLoading = true
      getAllPrivateRegions({
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName,
        privateRegion: query
      })
        .then((res) => {
          this.privateRegionOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.privateRegionLoading = false
        })
    },
    /**
     * @description: 磁盘类型查询
     * @param {*} query
     * @return {*}
     */
    diskTypeRemoteQuery(query) {
      this.diskTypeLoading = true
      // 通用参数
      const params = {
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName
      }
      const index = this.filterOptions.indexOf('diskType')
      for (let i = 0; i < index; i++) {
        params[this.filterOptions[i]] = this[this.filterOptions[i]]
      }
      params['diskType'] = query
      getDiskTypeInfoForSelect(params)
        .then((res) => {
          this.diskTypeOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.diskTypeLoading = false
        })
    },
    /**
     * @description: 镜像查询
     * @param {*} query
     * @return {*}
     */
    imageIdRemoteQuery(query) {
      this.imageIdLoading = true
      // 通用参数
      const params = {
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName
      }
      const index = this.filterOptions.indexOf('imageId')
      for (let i = 0; i < index; i++) {
        params[this.filterOptions[i]] = this[this.filterOptions[i]]
      }
      params['imageId'] = query
      getImageInfoForSelect(params)
        .then((res) => {
          this.imageIdOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.imageIdLoading = false
        })
    },
    /**
     * @description: 规格查询
     * @param {*} query
     * @return {*}
     */
    flavorIdRemoteQuery(query) {
      this.flavorIdLoading = true
      // 通用参数
      const params = {
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName
      }
      const index = this.filterOptions.indexOf('flavorId')
      for (let i = 0; i < index; i++) {
        params[this.filterOptions[i]] = this[this.filterOptions[i]]
      }
      params['flavorId'] = query
      getFlavorInfoForSelect(params)
        .then((res) => {
          this.flavorIdOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.flavorIdLoading = false
        })
    },
    /**
     * @description: 镜像格式查询
     * @param {*} query
     * @return {*}
     */
    formatRemoteQuery(query) {
      this.formatLoading = true
      // 通用参数
      const params = {
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName
      }
      const index = this.filterOptions.indexOf('format')
      for (let i = 0; i < index; i++) {
        params[this.filterOptions[i]] = this[this.filterOptions[i]]
      }
      params['format'] = query
      getImageFormatForSelect(params)
        .then((res) => {
          this.formatOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.formatLoading = false
        })
    },
    /**
     * @description: 描述查询
     * @param {*} query
     * @return {*}
     */
    describeRemoteQuery(query) {
      this.describeLoading = true
      // 通用参数
      const params = {
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName
      }
      const index = this.filterOptions.indexOf('describe')
      for (let i = 0; i < index; i++) {
        params[this.filterOptions[i]] = this[this.filterOptions[i]]
      }
      // 描述参数特殊处理
      params[this.getDescribeKey()] = query
      const caller =
        this.activeInfo === 'image'
          ? getImageDescribeForSelect
          : this.activeInfo === 'flavor'
            ? getFlavorDescribeForSelect
            : getDiskTypeDescribeForSelect
      // 发起请求
      caller(params)
        .then((res) => {
          this.describeOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.describeLoading = false
        })
    },
    /**
     * @description: 成本查询
     * @param {*} query
     * @return {*}
     */
    costRemoteQuery(query) {
      this.costLoading = true
      // 通用参数
      const params = {
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName
      }
      const index = this.filterOptions.indexOf('cost')
      for (let i = 0; i < index; i++) {
        if (this.filterOptions[i] === 'describe') {
          params[this.getDescribeKey()] = this[this.filterOptions[i]]
        } else {
          params[this.filterOptions[i]] = this[this.filterOptions[i]]
        }
      }
      params['cost'] = query
      getFlavorCostForSelect(params)
        .then((res) => {
          this.costOptions = Array.isArray(res.data)
            ? res.data.slice(0, Math.min(res.data.length, 100))
            : []
        })
        .finally(() => {
          this.costLoading = false
        })
    },
    /**
     * @description: 区域变化
     * @param {*} val
     * @return {*}
     */
    regionIdChange(val) {
      const index = this.filterOptions.indexOf('regionId')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 可用区变化
     * @param {*} val
     * @return {*}
     */
    zoneIdChange(val) {
      const index = this.filterOptions.indexOf('zoneId')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 可用域变化
     * @param {*} val
     * @return {*}
     */
    privateRegionChange(val) {
      const index = this.filterOptions.indexOf('privateRegion')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 磁盘类型变化
     * @param {*} val
     * @return {*}
     */
    diskTypeChange(val) {
      const index = this.filterOptions.indexOf('diskType')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 镜像变化
     * @param {*} val
     * @return {*}
     */
    imageIdChange(val) {
      const index = this.filterOptions.indexOf('imageId')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 规格变化
     * @param {*} val
     * @return {*}
     */
    flavorIdChange(val) {
      const index = this.filterOptions.indexOf('flavorId')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 描述变化
     * @param {*} val
     * @return {*}
     */
    describeChange(val) {
      const index = this.filterOptions.indexOf('describe')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 镜像格式变化
     * @param {*} val
     * @return {*}
     */
    formatChange(val) {
      const index = this.filterOptions.indexOf('format')
      const options = this.filterOptions.slice(
        index + 1,
        this.filterOptions.length
      )
      this.resetAndRemoteQuery(options)
    },
    /**
     * @description: 成本变化
     * @param {*} val
     * @return {*}
     */
    costChange(val) {},
    /**
     * @description: 重置筛选数据及请求
     * @param {*} options
     * @return {*}
     */
    resetAndRemoteQuery(options) {
      if (options.includes('regionId')) {
        this.regionId = ''
        this.regionIdOptions = []
        this.regionIdRemoteQuery('') // 区域重新查询
      }
      if (options.includes('zoneId')) {
        this.zoneId = ''
        this.zoneIdOptions = []
        this.zoneIdRemoteQuery('') // 可用区重新查询
      }
      if (options.includes('privateRegion')) {
        this.privateRegion = ''
        this.privateRegionOptions = []
        this.privateRegionRemoteQuery('') // 可用域重新查询
      }
      if (options.includes('flavorId')) {
        this.flavorId = ''
        this.flavorIdOptions = []
        this.flavorIdRemoteQuery('') // 规格重新查询
      }
      if (options.includes('imageId')) {
        this.imageId = ''
        this.imageIdOptions = []
        this.imageIdRemoteQuery('') // 镜像重新查询
      }
      if (options.includes('diskType')) {
        this.diskType = ''
        this.diskTypeOptions = []
        this.diskTypeRemoteQuery('') // 磁盘类型重新查询
      }
      if (options.includes('format')) {
        this.format = ''
        this.formatOptions = []
        this.formatRemoteQuery('') // 镜像格式重新查询
      }
      if (options.includes('describe')) {
        this.describe = ''
        this.describeOptions = []
        this.describeRemoteQuery('') // 描述重新查询
      }
      if (options.includes('cost')) {
        this.cost = ''
        this.costOptions = []
        this.costRemoteQuery('') // 成本重新查询
      }
    },
    /**
     * @description: 重置搜索框
     * @return {*}
     */
    resetClick() {
      this.resetAndRemoteQuery(this.filterOptions)
      this.pageNo = 1 // 第一页
      this.loading = true
      this.getListData()
    },
    /**
     * @description: size变化
     * @param {*} size
     * @return {*}
     */
    sizeChange(size) {
      this.pageSize = size
      this.pageNo = 1 // 第一页
      this.getListData() // 请求数据
    },
    /**
     * @description: 切换页码
     * @param {*} pageNo
     * @return {*}
     */
    changePage(pageNo) {
      this.pageNo = pageNo
      this.getListData() // 请求数据
    },
    /**
     * @description: 统一处理请求
     * @param {*} caller
     * @param {*} params
     * @return {*}
     */
    handleInfoRequestAndResp(caller, params) {
      caller(params)
        .then((res) => {
          if (res.data) {
            this.totalNum = res.data.totalNum
            this.list = Array.isArray(res.data.result) ? res.data.result : []
            for (let i = 0; i < this.list.length; i++) {
              this.list[i].order = (this.pageNo - 1) * this.pageSize + i + 1 // 标号
            }
          } else {
            this.totalNum = 0
            this.list = []
          }
        })
        .catch(() => {
          this.totalNum = 0
          this.list = []
        })
        .finally(() => {
          this.loading = false
        })
    },
    /**
     * @description: 获取描述请求参数key
     * @return {*}
     */
    getDescribeKey() {
      return this.activeInfo === 'storage'
        ? 'diskDescribe'
        : this.activeInfo + 'Describe'
    },
    /**
     * @description: 获取数据
     * @return {*}
     */
    getListData() {
      const params = {
        cloudType: this.allCloudVendor[this.activeIndex].cloudName,
        accountName: this.allCloudVendor[this.activeIndex].accountName,
        pageNo: this.pageNo,
        pageSize: this.pageSize
      }
      this.filterOptions.forEach((element) => {
        let paramKey = element
        if (element === 'describe') {
          paramKey = this.getDescribeKey()
        }
        params[paramKey] = this[element]
      })
      this.handleInfoRequestAndResp(
        this.activeInfo === 'image'
          ? getAllImageInfo
          : this.activeInfo === 'flavor'
            ? getAllFlavorInfo
            : getAllDiskTypeInfo,
        params
      )
    },
    /**
     * @description: 搜索
     * @return {*}
     */
    queryClick() {
      this.loading = true
      this.pageNo = 1 // 第一页
      this.getListData()
    },
    /**
     * @description: 信息点击
     * @param {*} index
     * @param {*} type
     * @return {*}
     */
    infoClick(index, type) {
      this.activeIndex = index
      this.activeInfo = type
      this.activePrivate = this.isCloudVendorPrivate(
        this.allCloudVendor[this.activeIndex].cloudVendor
      )
      if (!this.activePrivate && type === 'image') {
        // 公有云镜像
        this.filterOptions = [
          'regionId',
          'zoneId',
          'flavorId',
          'imageId',
          'describe'
        ]
        this.columnOptions = [
          'cloudType',
          'regionId',
          'zoneId',
          'flavorId',
          'imageId',
          'describe'
        ]
      } else if (!this.activePrivate && type === 'flavor') {
        // 公有云规格
        this.filterOptions = [
          'regionId',
          'zoneId',
          'flavorId',
          'describe',
          'cost'
        ]
        this.columnOptions = [
          'cloudType',
          'regionId',
          'zoneId',
          'flavorId',
          'describe',
          'cost',
          'agencyCost'
        ]
      } else if (!this.activePrivate && type === 'storage') {
        // 公有云存储
        this.filterOptions = [
          'regionId',
          'zoneId',
          'flavorId',
          'diskType',
          'describe'
        ]
        this.columnOptions = [
          'cloudType',
          'regionId',
          'zoneId',
          'flavorId',
          'diskType',
          'describe'
        ]
      } else if (this.activePrivate && type === 'image') {
        // 私有云镜像
        this.filterOptions = ['imageId', 'format']
        this.columnOptions = [
          'cloudScope',
          'cloudType',
          'accountName',
          'imageId',
          'format'
        ]
      } else if (this.activePrivate && type === 'flavor') {
        // 私有云规格
        this.filterOptions = ['privateRegion', 'flavorId', 'describe']
        this.columnOptions = [
          'cloudScope',
          'cloudType',
          'accountName',
          'privateRegion',
          'flavorId',
          'describe',
          'pidle',
          'pmax'
        ]
      } else if (this.activePrivate && type === 'storage') {
        // 私有云存储
        this.filterOptions = ['privateRegion', 'describe']
        this.columnOptions = [
          'cloudScope',
          'cloudType',
          'accountName',
          'privateRegion',
          'diskType',
          'describe'
        ]
      }
      this.resetClick()
    },
    /**
     * @description: 导出
     * @return {*}
     */
    exportClick() {
      this.exportLoading = true // 展示导出loading
      // 请求
      getAllExport()
        .then((response) => {
          const fileNames =
            response.headers['content-disposition'].split('fileName=') // 读取文件名
          const fileName =
            fileNames.length > 1
              ? decodeURIComponent(fileNames[1])
              : '云商规格-成本清单.xls' // 解析文件名
          const blob = new Blob([response.data], {
            type: 'application/vnd.ms-excel'
          }) // 新建blob
          const elementA = document.createElement('a') // 创建 element a
          elementA.style.display = 'none' // 设置不可见
          elementA.href = window.URL.createObjectURL(blob) // 设置href
          elementA.download = fileName // 设置名称
          document.body.appendChild(elementA) // 添加到body
          elementA.click() // 模拟点击
          window.URL.revokeObjectURL(elementA.href) // 释放内存
        })
        .catch((err) => {
          console.log(err)
          this.$message.error('导出失败，请稍候再试') // 导出失败
        })
        .finally(() => {
          this.exportLoading = false // 取消loading
        })
    },
    /**
     * @description: 绘制线条
     * @return {*}
     */
    drawTreeLines() {
      const COLORS = {
        startColor: ['#39C1E5b2', '#39C1E5b2', '#39C1E5b2'],
        endColor: ['#A160F4', '#2CCDE3', '#38EBBC']
      }
      const idRoot = 'tree-root'
      this.allCloudVendor.forEach((element, index) => {
        // 云商画线
        const idCluster = 'cloud-' + index
        const startEle = document.getElementById(idRoot) // 起点
        const endEle = document.getElementById(idCluster) // 终点
        const leader_line = new LeaderLine(startEle, endEle, {
          startPlugColor: '#f440dbb2', // 渐变色开始色
          endPlugColor: '#39C1E5b2', // 渐变色结束色
          gradient: true,
          startSocket: 'bottom', // 在指引线开始的地方从元素底部开始
          endSocket: 'top', // 在指引线开始的地方从元素顶部结束
          size: 12,
          endPlug: 'behind',
          path: 'fluid'
        })
        allLeaderLines.push(leader_line)
        this.infos.forEach((info, findex) => {
          const idInfo = 'cloud-' + index + '-' + info
          const startEle = document.getElementById(idCluster) // 起点
          const endEle = document.getElementById(idInfo) // 终点
          const leader_line2 = new LeaderLine(startEle, endEle, {
            startPlugColor: COLORS.startColor[findex], // 渐变色开始色
            endPlugColor: COLORS.endColor[findex], // 渐变色结束色
            gradient: true,
            startSocket: 'bottom', // 在指引线开始的地方从元素底部开始
            endSocket: 'top', // 在指引线开始的地方从元素顶部结束
            size: 12,
            endPlug: 'behind',
            path: 'fluid'
          })
          allLeaderLines.push(leader_line2)
        })
      })

      LeaderLine.positionByWindowResize = false

      // 将线条添加到内部容器中
      const lineElms = document.querySelectorAll('.leader-line') // 获取所有线条
      lineElms.forEach((element) => {
        // 重新计算边界
        // svg线条相对于body绘制，重新添加到内部容器时需修改相对位置
        const leftGap = this.sidebar.opened ? 280 : 74
        const topGap = 146
        element.style.left =
          Number(element.style.left.replace('px', '')) - leftGap + 'px'
        element.style.top =
          Number(element.style.top.replace('px', '')) - topGap + 'px'
        document.getElementById('treeCtn').appendChild(element) // 添加
      })
      // 为tree容器设置滑动事件监听
      // const treeEle = document.getElementById('treeCtn')
      // treeEle.addEventListener(
      //   'scroll',
      //   AnimEvent.add(() => {
      //     for (const leaderLine of allLeaderLines) {
      //       // 更新线条位置
      //       leaderLine.position()
      //     }
      //   }),
      //   false
      // )
    },
    /**
     * @description: 动态计算部分布局参数
     * @return {*}
     */
    computeLayout() {
      // 云商树底部宽度动态计算
      const MIN_GAP_PX = 5 // 最小间距
      const treeBottomMinWidth = this.allCloudVendor.length * 360
      const mainCtnWidth = this.$refs.mainCtn.$el.clientWidth
      const cloudGapCount = 2 + (this.allCloudVendor.length - 1) * 2 // 云商之间的间隙
      const infoGapCount = this.allCloudVendor.length * 2 // 信息之间的间隙
      const allGapCount = cloudGapCount + infoGapCount // 总的间隙
      if (mainCtnWidth - treeBottomMinWidth > allGapCount * MIN_GAP_PX) {
        // 底部布局空间充裕 可分配部分宽度
        this.flavorMargin = Math.round(
          (mainCtnWidth - treeBottomMinWidth) / allGapCount
        )
        this.treeBottomMinWidth = treeBottomMinWidth
      } else {
        this.flavorMargin = MIN_GAP_PX // 最小间距
        this.treeBottomMinWidth =
          treeBottomMinWidth + allGapCount * MIN_GAP_PX + 'px'
      }
    },
    /**
     * @description: 初始化数据
     * @return {*}
     */
    initData() {
      allLeaderLines = []
      getAllCloudVendor().then((res) => {
        this.allCloudVendor = Array.isArray(res.data) ? res.data : []
        this.$nextTick(() => {
          this.computeLayout()
          setTimeout(() => {
            this.drawTreeLines()
          }, 200)
        })
        // 获取过滤数据项
        this.infoClick(0, 'image')
      })
    }
  }
}
</script>

<style lang="less" scoped>
@import "@/assets/css/common.less";
.flavor-ctn {
  min-height: calc(100vh - 90px);

  .main {
    padding: 20px 0;
    overflow-x: hidden;
  }

  .tree {
    position: relative;
    width: 100%;
    overflow-x: auto;
    margin-top: 20px;
    background: #fefeff;
    border-radius: 8px 8px 0px 0px;
    border: 1px solid #ececec;
    background-image: radial-gradient(#e6e6e6 7%, transparent 0);
    background-size: 40px 40px;
    box-sizing: border-box;
    padding: 30px 0;

    .top {
      display: flex;
      align-items: center;
      justify-content: center;

      .item {
        display: flex;
        align-items: center;

        .line {
          width: 2px;
          height: 46px;
          background: #f440db;
        }

        .content {
          margin: 0 4px;
          padding: 9px 20px;
          background: #f440db;
          border-radius: 1px;
          .textStyle(20px , 600, #FFFFFF);
          line-height: 28px;
        }
      }
    }

    .center {
      margin-top: 120px;
      display: flex;
      align-items: center;
      justify-content: space-around;

      .cloud {
        padding: 3px 10px;
        background: #ffffff;
        border-radius: 1px;
        .textStyle(18px , 600, #B1AAE9);
        line-height: 25px;
      }
    }

    .bottom {
      margin-top: 120px;
      display: flex;
      align-items: center;
      justify-content: space-around;

      .infos {
        min-width: 360px;
        display: flex;
        align-items: center;
        justify-content: space-between;

        .info {
          cursor: pointer;
          display: flex;
          align-items: center;

          .line {
            width: 2px;
            height: 36px;
            background: #a160f4;
          }

          .content {
            min-width: 92px;
            margin: 0 4px;
            padding: 5px 10px;
            background: #a160f4;
            border-radius: 1px;
            .textStyle(18px , 600, #FFFFFF);
            line-height: 26px;

            &.flavor {
              min-width: 128px;
            }
          }

          &.active {
            .line {
              background: #d441f4;
            }
            .content {
              background: linear-gradient(90deg, #ef40f4 0%, #b660f4 100%);
            }
          }

          &.flavor {
            // margin: 0 35px;
            .line {
              background: #2ccde3;
            }
            .content {
              background: #2ccde3;
            }
          }
          &.flavor.active {
            .line {
              background: #19a1dd;
            }
            .content {
              background: linear-gradient(270deg, #1a9fdd 0%, #06d4e5 100%);
            }
          }

          &.storage {
            .line {
              background: #38ebbc;
            }
            .content {
              background: #38ebbc;
            }
          }
          &.storage.active {
            .line {
              background: #4be028;
            }
            .content {
              background: linear-gradient(270deg, #4bdf21 0%, #38ebbc 100%);
            }
          }
        }
      }
    }
  }

  .list {
    box-sizing: border-box;
    padding: 25px 20px 0;
  }

  .filter {
    margin-bottom: 20px;
  }

  .custom-table {
    .el-table::before {
      background-color: #e9e9e9;
    }
    /deep/ .listHeaderCell {
      height: 40px;
      padding: 0;
      box-sizing: border-box;
      &:first-child {
        padding-left: 20px;
      }
    }

    /deep/ .el-table__body {
      .el-table__row td {
        height: 40px;
        padding: 0;
        &:first-child {
          padding-left: 20px;
        }
      }
    }
  }
}
</style>
